package com.huawang.mdesign.model.service.util.mindmap;

import cn.hutool.core.util.ZipUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.huawang.business.constants.ErrorCode;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.util.ObjectMapperFactory;
import com.huawang.mdesign.model.service.constant.mindmap.MindMapEnum;
import com.huawang.mdesign.model.service.util.mindmap.xmind.Root;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.*;

/**
 * XMind解析类
 *
 * @author admin
 */
@Slf4j
@Component
public class XMindUtil implements MindMap {

    @Override
    public boolean support(@NotNull String sourceFile) {
        return StringUtils.isNotBlank(sourceFile) && sourceFile.endsWith(MindMapEnum.X_MIND.getSuffix());
    }

    @Override
    public @NotNull List<Root> read(@NotNull String sourceFile) {
        return parse(sourceFile);
    }

    /**
     * 解压并读取XMind
     *
     * @param sourceFile 源文件路径
     * @return 文件内容
     */
    @SneakyThrows
    @NotNull
    public static List<Root> parse(@NotNull String sourceFile) {
        File source = new File(sourceFile);
        if (!source.exists() || !source.isFile() || !sourceFile.endsWith(MindMapEnum.X_MIND.getSuffix())) {
            return Collections.emptyList();
        }

        //unzip
        File dir = ZipUtil.unzip(source);
        return ObjectMapperFactory.getMapper().readValue(getContent(dir, MindMapEnum.X_MIND.getTargetFile()),
                new TypeReference<List<Root>>() {
                });
    }

    /**
     * 遍历文件夹，获取指定文件
     *
     * @param dir        文件夹
     * @param targetFile 指定文件
     * @return 指定文件
     */
    @NotNull
    public static File getContent(@Nullable File dir, @Nullable String targetFile) {
        return Optional.ofNullable(dir)
                .filter(e -> StringUtils.isNotBlank(targetFile))
                .map(File::listFiles)
                .filter(e -> e.length > 0)
                .flatMap(e -> Arrays.stream(e).filter(File::isFile).filter(k -> k.getName().endsWith(targetFile)).findFirst())
                .orElseThrow(() -> AbortExecutionException.build(ErrorCode.FILE_URL_NOT_EXIST));
    }

}
